package com.apes.fn.server.productRequireManage.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.mdm.offer.model.DeptOfferGroup;
import com.apes.fn.mdm.offer.model.OfferGroup;
import com.apes.fn.mdm.offer.repository.DeptOfferGroupRepository;
import com.apes.fn.mdm.offer.repository.OfferGroupRepository;
import com.apes.fn.server.productRequire.*;
import com.apes.fn.server.productRequireManage.model.ReplenishmentBusinessImpAbstract;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.cache.Cache;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.plugin.soe.store.database.repository.SceneRepository;
import com.apes.framework.util.MapUtil;
import com.apes.hr.base.model.Employee;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.account.tax.repository.TaxRepository;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.masterdata.product.repository.ProductUomRepository;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrder;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrderItem;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service("supplierOrderService")
public class SupplierOrderService extends ReplenishmentBusinessImpAbstract {
    @Autowired
    private ProductRequireRepository productRequireRepository;
    @Autowired
    private OutboxSubscriberService outboxSubscriberService;
    @Autowired
    private ProductAccountService productAccountService;
    @Autowired
    private ProductRequireService productRequireService;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private LocationRepository locationRepository;
    @Autowired
    private ProductUomRepository productUomRepository;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private Cache cache;
    @Autowired
    private EnumerationRepository enumerationRepository;
    @Autowired
    private ProductRequireItemRepository productRequireItemRepository;


    private static final String SUPPLIER_ID_AND_REQUIRE_ITEMS = "supplierIdAndRequireItems";

    @Override
    public Map sendOrder(JSONObject getJO) { // 考虑多人操作相同数据问题
        JSONArray itemDataArray = getJO.getJSONArray("purchaseRequireItems");
//        JSONArray requireItemErrorLogs = getJO.getJSONArray("requireItemErrorLog");
//        this.writeItemLoggerAndUpdateRequireItem(requireItemErrorLogs);

        // 更新要货单为锁定
        Set<String> productRequireIds = filterRequireIds(itemDataArray);
        List<ProductRequire> requires = productRequireRepository.findAll(JpaDsl.toCriteria("id", "in", productRequireIds));
        requires.forEach(require -> {
            if (require.getState().equals("locked")) throw new RuntimeException(String.format("要货单[%s]正在处理中！请稍后再试！！", require.getId()));
            JSONObject theSameObj = (JSONObject) itemDataArray.stream().filter(itemData -> require.getId().equals(((JSONObject) itemData).get("productRequireId"))).findFirst().orElse(new JSONObject());
            if (theSameObj.getInteger("version") != require.getVersion()) throw new RuntimeException("单据已变动, 请重新查询, 要货单号: " + require.getId());

            require.setState("locked");

        });
        productRequireService.batchUpdateState(requires);

        // 放入事务发件箱
        outboxSubscriberService.commonSendRequest("local:supplierOrder.generatorSupplierOrder", "generatorSupplierOrder：" + new Random().nextInt(50000),
                new JSONObject(MapUtil.mapper("requireIds", productRequireIds, "item", itemDataArray)));

        return null;
    }

    // 明细异常日志写入
//    private void writeItemLoggerAndUpdateRequireItem(JSONArray requireItemErrorLogs) {
//        if (requireItemErrorLogs == null || requireItemErrorLogs.isEmpty()) return;
//        requireItemErrorLogs.forEach(requireItemErrorLog -> {
//            JSONObject requireItemErrorLogObj = (JSONObject) requireItemErrorLog;
//            String errorMessage = requireItemErrorLogObj.getString("errorMessage");
//            ProductRequireItem requireItem = productRequireItemRepository.findOne(requireItemErrorLogObj.getString("id"));
//            requireItem.setErrorMessage(errorMessage);
//            productRequireItemRepository.save(requireItem);
//
//            this.appendRequireLogger(requireItem.getProductRequire().getId(), "ProductRequire", "生成供应商订单", 0,
//                    errorMessage + ", 商品：" + requireItem.getProduct().getId());
//        });
//    }

    // 供应商平台订单 - 取消
    public void supplierCancel(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        outboxSubscriberService.commonSendRequest("local:supplierOrder.supplierCancelMessageForward", "cancel_supplier_id：" + getJO.getString("supplierRef"), getJO);
    }

    // 供应商发货 - 生成采购订单
    public void supplierGeneratorPurchaseOrder(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        outboxSubscriberService.commonSendRequest("local:supplierOrder.generatorPurchaseOrder", "supplierDeliver: " + getJO.getString("supplierRef"), request.getJO());
    }

    // 供应商终止订单
    public void supplierStopPurchaseOrder(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        outboxSubscriberService.commonSendRequest("local:supplierOrder.stopPurchaseOrder", "supplierStop: " + getJO.getString("supplierRef"), request.getJO());
    }

    // 供应商平台生成三方订单异常
    public void externalBelowError(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        outboxSubscriberService.commonSendRequest("local:supplierOrder.externalBelowErrorOutbox", "supplierBelowError：" + getJO.getString("productRequire"), getJO);

    }


    // 过滤要货单号
    private Set<String> filterRequireIds(JSONArray item) {
        return item.stream().map(itemDataObj -> {
            JSONObject itemData = (JSONObject) itemDataObj;
            return itemData.getString("productRequireId");
        }).distinct().collect(Collectors.toSet());
    }

    @OutboxSubscriber(id="local:supplierOrder.supplierCancelMessageForward", name="供应商订单取消")
    public void supplierCancelMessageForward(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject payload = JSONObject.parseObject(outboxPayloadWrapper.getPayload());

        String operate = Objects.isNull(payload.get("operate"))?"供应商订单取消":payload.getString("operate");
        String requireId = payload.getString("productRequire");
        String supplierRef = payload.getString("supplierRef");
        JSONArray itemArray = payload.getJSONArray("purchaseItems");
        ProductRequire require = productRequireRepository.findOne(requireId);

        // 写入要货扩展表终止数量
        List<Map> requireDatas = new ArrayList<>();
        itemArray.forEach(supplierItem -> {
            JSONObject supplierIO = (JSONObject) supplierItem;
            String productId = supplierIO.getString("productId");
            String sourceItemId = supplierIO.getString("sourceItemId");
            double qty = supplierIO.getDoubleValue("qty");
            Product product = productRepository.findOne(productId);

            // 写入要货扩展终止数量
            Map requireExpand = MapUtil.mapper("distributionId", supplierRef, "originItemId", sourceItemId, "cancelQty", qty);
            Map requireExpandResult = invoke("stock.productRequireExpandService.updateCancelQty", requireExpand);
            ProductUom purchaseUom = productUomRepository.findOne(Long.valueOf(requireExpandResult.get("uomId").toString()));
            PartyRole distributionCompany = partyRoleRepository.findOne(requireExpandResult.get("distributionCompanyId").toString());

            // 增加要货制单梳理
            ProductRequireItem requireItem = productRequireItemRepository.findOne(sourceItemId);
            double minAssignedAty = purchaseUom.computeQty(qty, requireItem.getUom(), true);
            double stockRequireBillingQty = requireItem.currentStopQty(minAssignedAty);
            if (stockRequireBillingQty > 0) {
                productAccountService.setProductRequireBilling(product, require.getLocation(), purchaseUom, stockRequireBillingQty,
                        "supplier", supplierRef, sourceItemId, operate, require.getLocation().getCompany(), requireId);
            }

            // 减少订货在途
            productAccountService.setProductPurchasingWay(product, require.getLocation(), purchaseUom, -qty, distributionCompany);

            // 组装要修改的要货明细
            requireDatas.add(MapUtil.mapper( "qtyAssigned", -qty, "id", sourceItemId));

        });

        // 修改要货分配数量
        invoke("stock.productRequireService.updateAssignmentQty", MapUtil.mapper("id", requireId, "distributionId", supplierRef, "item", requireDatas));

        // 写入日志
        this.appendRequireLogger(requireId, "ProductRequire", operate, 0, "供应商订单号: " + supplierRef);

        // 移除缓存中的数据
        cache.remove(SUPPLIER_ID_AND_REQUIRE_ITEMS, supplierRef + requireId);
    }


    @OutboxSubscriber(id="local:supplierOrder.stopPurchaseOrder", name="供应商平台终止订单")
    public void stopPurchaseOrder(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject payload = JSONObject.parseObject(outboxPayloadWrapper.getPayload());

        // 取消采购订单
        payload.put("operatorName", "system");
        invoke("purchase.purchaseService.externalCancelCall", payload);

    }


    @OutboxSubscriber(id="local:supplierOrder.generatorPurchaseOrder", name="供应商平台生成采购订单")
    public void generatorPurchaseOrder(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject payload = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        String requireId = payload.getString("productRequire");
        String supplierId = payload.getString("supplierId");
        String supplierRef = payload.getString("supplierRef");
        String supplierNumber = payload.getString("supplierNumber");

        // 获取缓存中的数据
        JSONArray requireItems = (JSONArray) cache.get(SUPPLIER_ID_AND_REQUIRE_ITEMS, supplierRef + requireId);

        // 分组
        Map<JSONObject, List> requireItemGroupPur = this.requireItemGroup(requireItems, supplierId);

        // 拼接并生成采购
        requireItemGroupPur.forEach((k, v) -> {
            PurchaseOrder purchaseOrder = this.appendPurchaseOrder(k, supplierRef, supplierNumber);
            List<PurchaseOrderItem> orderItems = this.appendPurchaseOrderItem(v, payload.getJSONArray("purchaseItems"), purchaseOrder);
            purchaseOrder.setPurchaseItems(orderItems);

            PurchaseOrder purchaseOrder1 = invoke("purchase.order.create", MapUtil.mapped(purchaseOrder));
            purchaseOrder1.setState("confirmed");
            purchaseOrder1.setApproveUid(partyRoleRepository.findOne("system"));
            invoke("purchase.order.approve", MapUtil.mapped(purchaseOrder1));

            // 记录要货日志
            this.appendRequireLogger(requireId, "ProductRequire", "供应商发货", 0, "采购订单号: " + purchaseOrder1.getId());

        });

        cache.remove(SUPPLIER_ID_AND_REQUIRE_ITEMS, supplierRef + requireId);
    }

    // 根据 供应商、部门、平台等分组为采购订单拆单做准备
    private Map requireItemGroup(JSONArray itemDataArray, String supplierId) {
        return itemDataArray.stream()
                .filter(itemData -> {return supplierId.equals(((JSONObject) itemData).getJSONObject("supplier").getString("id"));}) // 必须是相同供应商
                .collect(Collectors.groupingBy(requireItem -> {
            JSONObject requireItemObj = (JSONObject) requireItem;
            Map key = MapUtil.mapper("companyId", requireItemObj.getJSONObject("company").getString("id"),
                    "supplierId", requireItemObj.getJSONObject("supplier").getString("id"),
                    "deptId", requireItemObj.getJSONObject("dept").getString("id"),
                    "contractId", requireItemObj.getJSONObject("contract").getString("id"),
                    "locationId", requireItemObj.getJSONObject("location").getString("id"),
                    "platformId", requireItemObj.getJSONObject("platform").getString("id"),
                    "productRequireId", requireItemObj.getString("productRequireId"),
                    "customerExpand", requireItemObj.getJSONObject("customerExpand") == null?new JSONObject():requireItemObj.getJSONObject("customerExpand"),
                    "carLicense", requireItemObj.getJSONObject("customerExpand") == null?"":requireItemObj.getJSONObject("customerExpand").getString("carLicense"),
                    "siteId", this.specialColumnObtainValue(requireItemObj.get("site")),
                    "purchasingGroupId", this.specialColumnObtainValue(requireItemObj.get("purchasingGroup")));

            return new JSONObject(key);
        }));
    }

    // 界面选择的是对象，默认传值给界面是 Map
    private String specialColumnObtainValue(Object value) {
        if (value instanceof JSONObject) {
            return ((JSONObject) value).getString("id");
        } else if (value instanceof JSONArray) {
            return ((JSONArray) value).getJSONObject(0).getString("id");
        }
        return "";
    }



    public PurchaseOrder appendPurchaseOrder(JSONObject expandInfoObj, String supplierRef, String supplierNumber) {
        PurchaseOrder order = new PurchaseOrder();
        PartyRole createPerple = partyRoleRepository.findOne("system");
        String purchasingGroupId = expandInfoObj.getString("purchasingGroupId");
        order.setState("sent");
        order.setScene(SpringManager.getBean(SceneRepository.class).findOne("PO001"));
        order.setClerk(createPerple);
        order.setCreator(createPerple.getId());
        order.setCreateUid(createPerple);
        order.setCreateDate(new Date());
        order.setPurchasingGroup(purchasingGroupId);
        order.setCustomerExpandId(expandInfoObj.getJSONObject("customerExpand").getString("id"));

        Contract contract = SpringManager.getBean(ContractRepository.class).findOne(expandInfoObj.getString("contractId"));
        order.setContract(contract);
        order.setCooperation(contract.getCooperation());
        order.setDept(SpringManager.getBean(DeptRepository.class).findOne(expandInfoObj.getString("deptId")));
        order.setSupplier(partyRoleRepository.findOne(expandInfoObj.getString("supplierId")));
        order.setMoveType(contract.getMoveType() == null?enumerationRepository.findOne("direct"):contract.getMoveType());
        order.setLocation(SpringManager.getBean(LocationRepository.class).findOne(expandInfoObj.getString("locationId")));
        order.setCompany(partyRoleRepository.findOne(expandInfoObj.getString("companyId")));
        order.setCarLicense(expandInfoObj.getString("carLicense"));
        order.setProductRequire(expandInfoObj.getString("productRequireId"));
        order.setSource(expandInfoObj.getString("productRequireId"));
        order.setSourceType("ProductRequire");
        order.setSourceTypeName("赋能要货单");
        order.setSupplierRef(supplierRef);
        order.setSupplierType("supplier");
        order.setExternalDocument(supplierNumber);
        order.setSiteId(this.obtainSite(expandInfoObj.getString("locationId"), purchasingGroupId, expandInfoObj.getString("siteId")));
        return order;
    }

    // 拼接采购订单明细
    private List<PurchaseOrderItem> appendPurchaseOrderItem(List requireItemArray, JSONArray supplierItems, PurchaseOrder purOrder) {
        List<PurchaseOrderItem> orderItems = new ArrayList<>();
        supplierItems.forEach(supplierItem -> {
            requireItemArray.forEach(requireItem -> {
                JSONObject requireItemObj = (JSONObject) requireItem;
                String requireItemId = requireItemObj.getString("id");
                if (!((JSONObject) supplierItem).getString("sourceItemId").equals(requireItemId)) return;

                PurchaseOrderItem orderItem = new PurchaseOrderItem();
                double distributionQty = requireItemObj.getDoubleValue("distributionQty");
                double P001 = requireItemObj.getDoubleValue("P001");
                long taxId = requireItemObj.getJSONObject("tax").getLong("id");

                orderItem.setPurchaseOrder(purOrder);
                orderItem.setSourceState(enumerationRepository.findOne(requireItemObj.getString("sourceStateId")));
                orderItem.setProduct(productRepository.findOne(requireItemObj.getJSONObject("product").getString("id")));
                orderItem.setTax(SpringManager.getBean(TaxRepository.class).findOne(taxId));
                orderItem.setUom(productUomRepository.findOne(requireItemObj.getJSONObject("purchaseUom").getLong("id")));
                orderItem.setProductUomQty(distributionQty);
                orderItem.setEffectiveQty(distributionQty);
                orderItem.setDemandQty(distributionQty);
                orderItem.setPriceUnit(P001);

                Map getPriceCondi = new HashMap();
                getPriceCondi.put("companyId", purOrder.getCompany().getId());
                getPriceCondi.put("taxId", taxId);
                getPriceCondi.put("priceUnit", P001);
                getPriceCondi.put("qty", distributionQty);
                Map reponsePrice = invoke("account.tax.computeTaxAmount", getPriceCondi);
                orderItem.setPriceSubtotal(Double.parseDouble(reponsePrice.get("totalExcluded").toString()));
                orderItem.setPriceTax(Double.parseDouble(reponsePrice.get("taxAmt").toString()));
                orderItem.setPriceTotal(Double.parseDouble(reponsePrice.get("totalIncluded").toString()));
                orderItem.setPriceCeiling(requireItemObj.getDoubleValue("priceCeiling"));
                orderItem.setExpectedArrivalTime(requireItemObj.getDoubleValue("expectedArrivalTime"));
                orderItem.setSourceState(enumerationRepository.findOne(requireItemObj.getString("sourceStateId")));
                orderItem.setSourceItemId(requireItemObj.getString("id"));
                orderItems.add(orderItem);
            });
        });

        return orderItems;
    }

    // 获取站点
    private String obtainSite(String locationId, String purchasingGroupId, String siteId) {
        if (StringUtils.hasText(purchasingGroupId) && StringUtils.isEmpty(siteId)) {
            Map purchaseGroupSite = invoke("cm.purchasingGroup.queryPurchaseGroupSite", MapUtil.mapper("id", purchasingGroupId, "locationId", locationId));
            return purchaseGroupSite.get("siteId").toString();
        } else {
            return siteId;
        }
    }


    @OutboxSubscriber(id="local:supplierOrder.generatorSupplierOrder", name="要货单生成供应商订单")
    public void generatorSupplierOrder(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject payload = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        Map<Object, List<Object>> itemGroups = payload.getJSONArray("item").stream().collect(Collectors.groupingBy(item -> {
            JSONObject data = (JSONObject) item;
            data.getJSONObject("store").putAll(this.findStoreContacts(data.getJSONObject("store").getString("id")));
            return ((JSONObject) item).getString("productRequireId");
        }));
        payload.put("item", itemGroups);
        JSONObject obj = JSONObject.parseObject(invoke("sp.OrderForm.establishOrderForm", MapUtil.mapper("item", itemGroups)));
        payload.put("supplierResult", obj);

        // 发送请求修改 要货单修改影响到的数据
        outboxSubscriberService.commonSendRequest("local:supplierOrder.updateRequireAbout", "updateRequireAbout: " + new Random().nextInt(100000), payload);

    }

    @OutboxSubscriber(id="local:supplierOrder.updateRequireAbout", name="要货单生成供应商订单-数据联动")
    public void updateRequireAbout(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject payload = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        JSONArray requireIds = payload.getJSONArray("requireIds");
        JSONObject item = payload.getJSONObject("item");

        JSONObject supplierResult = payload.getJSONObject("supplierResult");
        JSONObject header = supplierResult.getJSONObject("header");
        String code = header.getString("code");
        String message = header.getString("message");

        // 释放要货单锁定状态
        List<ProductRequire> requires = productRequireRepository.findAll(JpaDsl.toCriteria("id", "in", requireIds));
        requires.forEach(require -> {
            if (require.getState().equals("locked")) {
                require.setState("approve");
            }
        });
        productRequireService.batchUpdateState(requires);

        // 失败记录日志，并返回
        if (!"success".equals(code)) {
            requireIds.forEach(ids -> {
                this.appendRequireLogger(ids.toString(), "ProductRequire", "生成供应商订单",0, "失败原因：" + message);
            });
            return;
        }

        // 成功
        ParamValue param = new ParamValue();
        supplierResult.getJSONObject("body").getJSONArray("orderForms").forEach(orderForm -> {
            JSONObject orderFormO = (JSONObject) orderForm;
            String supplierOrderId = orderFormO.getString("id");
            String relatedNumber = orderFormO.getString("relatedNumber");

            item.forEach((k, v) -> {
                List<JSONObject> requireItemList = new ArrayList<>();
                if (!relatedNumber.equals(k)) return;

                // 发送过去给供应商的商品明细是全盘接收
                ((JSONObject) orderForm).getJSONArray("detailList").forEach(detailList -> { // 供应商订单明细
                    JSONArray vArray = (JSONArray) v;
                    for (int i = 0, iLen = vArray.size(); i < iLen; i++) {
                        JSONObject requireO = vArray.getJSONObject(i);
                        if (!((JSONObject) detailList).getString("productRequireItem").equals(requireO.getString("id"))) continue;
                        ProductUom requireUom = productUomRepository.findOne(requireO.getJSONObject("requireUom").getLong("id"));
                        double distributionQty = requireO.getDoubleValue("distributionQty");

                        // 缓存数据
                        param.settingValue(requireO.getJSONObject("company").getString("id"), requireO.getJSONObject("product").getString("id"),
                                requireO.getJSONObject("location").getString("id"), requireO.getString("id"), requireO.getString("productRequireId"), requireO.getJSONObject("purchaseUom").getLong("id"));


                        // 创建要货缺口分配表
                        Map requireExpand = MapUtil.mapper("origin", param.getRequireId(), "originItemId", requireO.get("id"), "originBusinessType", "ProductRequire",
                                "productId", MapUtil.mapper("id", param.getProductId()),
                                "productUomId", MapUtil.mapper("id", param.getPurchaseUomId()),
                                "distributionCompany", MapUtil.mapper("id", param.getCompanyId()),
                                "distributionId", supplierOrderId, "assignQty", distributionQty);
                        invoke("stock.productRequireExpand.save", requireExpand);

                        // 获取实际可减要货制单数量
                        ProductUom purchaseUom = param.getCacheProductUom().get(param.getPurchaseUomId());
                        double minAssignedAty = purchaseUom.computeQty(distributionQty, requireUom, true);
                        double stockRequireBillingQty = productRequireItemRepository.findOne(param.getRequireItemId()).getCurrentAssigentQty(minAssignedAty);

                        // 减少要货制单数量
                        productAccountService.setProductRequireBilling(param.getCacheProduct().get(param.getProductId()), param.getCacheLocation().get(param.getLocationId()), requireUom,
                                -stockRequireBillingQty, "supplier", supplierOrderId, param.getRequireItemId(), "生成供应商订单", param.getCacheLocation().get(param.getLocationId()).getCompany(), param.getRequireId());

                        // 增加订货在途
                        productAccountService.setProductPurchasingWay(param.getCacheProduct().get(param.getProductId()), param.getCacheLocation().get(param.getLocationId()), purchaseUom,
                                distributionQty, partyRoleRepository.findOne(param.getCompanyId()));

                        // 拼接要货数据
                        requireItemList.add(new JSONObject(MapUtil.mapper("orderQty", -1 * 0, "qtyAssigned", distributionQty, "id", param.getRequireItemId())));
                    }
                });
                // 缓存订单数据
                cache.put(SUPPLIER_ID_AND_REQUIRE_ITEMS, supplierOrderId + k, v);

                // 修改要货明细已分配数量
                invoke("stock.productRequireService.updateAssignmentQtyAndOrderQty", MapUtil.mapper("id", k, "distributionId", supplierOrderId, "item", requireItemList));
            });

            // 写日志
            this.appendRequireLogger(relatedNumber, "ProductRequire", "生成供应商订单", 0, "供应商订单号：" + supplierOrderId);

        });

    }

    private void appendRequireLogger(String businessKey, String businessType, String operate, int operatorId, String remark) {
        invoke("ir.logger.save",
                MapUtil.mapper("businessKey", businessKey, "businessType", businessType, "operator_id", operatorId, "operate", operate,
                        "businessDate", new Date(), "remark", remark));
    }


    @Data
    class ParamValue {
        private Map<String, Product> cacheProduct = new HashMap<>();
        private Map<String, Location> cacheLocation = new HashMap<>();
        private Map<Long, ProductUom> cacheProductUom = new HashMap<>();

        private String companyId;
        private String productId;
        private String locationId;
        private String requireItemId;
        private String requireId;
        private long purchaseUomId;

        public void settingValue(String companyId, String productId, String locationId, String requireItemId, String requireId, long purchaseUomId) {
            this.companyId = companyId;
            this.productId = productId;
            this.locationId = locationId;
            this.requireItemId = requireItemId;
            this.requireId = requireId;
            this.purchaseUomId = purchaseUomId;

            this.setCacheProduct(productId);
            this.setCacheLocation(locationId);
            this.setCacheProductUom(purchaseUomId);
        }

        public void setCacheProduct(String productId) {
            if (Objects.isNull(cacheProduct.get(productId))) {
                cacheProduct.put(productId, productRepository.findOne(productId));
            }
        }

        public void setCacheLocation(String locationId) {
            if (Objects.isNull(cacheLocation.get(locationId))) {
                cacheLocation.put(locationId, locationRepository.findOne(locationId));
            }
        }

        public void setCacheProductUom(long purchaseUomId) {
            if (Objects.isNull(cacheProductUom.get(purchaseUomId))) {
                cacheProductUom.put(purchaseUomId, productUomRepository.findOne(purchaseUomId));
            }
        }
    }



    @OutboxSubscriber(id="local:supplierOrder.externalBelowErrorOutbox", name = "供应商平台生成三方订单錯誤")
    public void externalBelowErrorOutbox(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject payload = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        String sourceItemId = payload.getString("sourceItemId");
        String productRequireId = payload.getString("productRequire");

        // 更新要货明细异常字段
        ProductRequire productRequire = productRequireRepository.findOne(productRequireId);
        productRequire.setLastUpdatedStamp(new Date());
        ProductRequireItem requireI = productRequire.getProductRequireItems().stream().filter(requireItem -> requireItem.getId().equals(sourceItemId)).findFirst().orElse(new ProductRequireItem());
        requireI.setErrorMessage(payload.getString("errorMessage"));
        productRequireRepository.saveAndFlush(productRequire);

        // 写入异常日志
        this.appendRequireLogger(productRequireId, "ProductRequire", "供应商平台生成三方订单錯誤",  0, "供应商订单号: " + payload.get("supplierRef"));
    }

    // 获取人员给供应商平台
    private Map findStoreContacts(String storeId) {
        Employee emp =  invoke("hr.employee.findByWorkBranchAndPostEQManager", MapUtil.mapper("id", storeId));
        if (emp != null && StringUtils.hasText(emp.getName())) {
            return MapUtil.mapper("contacts", emp.getName(), "telephone", emp.getMobileNumber());
        } else {
            DeptOfferGroup deptOfferGroup = getBean(DeptOfferGroupRepository.class).findByDeptId(storeId);
            List<OfferGroup> offerGroups = getBean(OfferGroupRepository.class).findByNameIn(Arrays.asList(deptOfferGroup.getName()));
            if (!offerGroups.isEmpty()) {
                return MapUtil.mapper("contacts", offerGroups.get(0).getPersonnelName().getName(), "telephone", offerGroups.get(0).getPersonnelName().getMobileNumber());
            }
        }
        return new HashMap();
    }
}
